/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkDWrite_DEFINED
#define SkDWrite_DEFINED

#include "include/core/SkFontStyle.h"
#include "include/private/base/SkTemplates.h"

#include <dwrite.h>
#include <winsdkver.h>

class SkString;

// //////////////////////////////////////////////////////////////////////////////
// Factory

IDWriteFactory *sk_get_dwrite_factory();

// //////////////////////////////////////////////////////////////////////////////
// String conversion

/* * Prefer to use this type to prevent template proliferation. */
typedef skia_private::AutoSTMalloc<16, WCHAR> SkSMallocWCHAR;

/* * Converts a utf8 string to a WCHAR string. */
HRESULT sk_cstring_to_wchar(const char *skname, SkSMallocWCHAR *name);

/* * Converts a WCHAR string to a utf8 string.
 * @param nameLen the number of WCHARs in the name.
 */
HRESULT sk_wchar_to_skstring(WCHAR *name, int nameLen, SkString *skname);

// //////////////////////////////////////////////////////////////////////////////
// Locale

HRESULT sk_get_locale_string(IDWriteLocalizedStrings *names, const WCHAR *preferedLocale, SkString *skname);

typedef int(WINAPI *SkGetUserDefaultLocaleNameProc)(LPWSTR, int);
HRESULT SkGetGetUserDefaultLocaleNameProc(SkGetUserDefaultLocaleNameProc *proc);

// //////////////////////////////////////////////////////////////////////////////
// Table handling

class AutoDWriteTable {
public:
    AutoDWriteTable(IDWriteFontFace *fontFace, UINT32 beTag) : fExists(FALSE), fFontFace(fontFace)
    {
        // Any errors are ignored, user must check fExists anyway.
        fontFace->TryGetFontTable(beTag, reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists);
    }
    ~AutoDWriteTable()
    {
        if (fExists) {
            fFontFace->ReleaseFontTable(fLock);
        }
    }

    const uint8_t *fData;
    UINT32 fSize;
    BOOL fExists;

private:
    // Borrowed reference, the user must ensure the fontFace stays alive.
    IDWriteFontFace *fFontFace;
    void *fLock;
};
template <typename T> class AutoTDWriteTable : public AutoDWriteTable {
public:
    static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2, T::TAG3);
    AutoTDWriteTable(IDWriteFontFace *fontFace) : AutoDWriteTable(fontFace, tag) {}

    const T *get() const
    {
        return reinterpret_cast<const T *>(fData);
    }
    const T *operator->() const
    {
        return reinterpret_cast<const T *>(fData);
    }
};

// //////////////////////////////////////////////////////////////////////////////
// Style conversion

struct DWriteStyle {
    explicit DWriteStyle(const SkFontStyle &pattern)
    {
        fWeight = (DWRITE_FONT_WEIGHT)pattern.weight();
        fWidth = (DWRITE_FONT_STRETCH)pattern.width();
        switch (pattern.slant()) {
            case SkFontStyle::kUpright_Slant:
                fSlant = DWRITE_FONT_STYLE_NORMAL;
                break;
            case SkFontStyle::kItalic_Slant:
                fSlant = DWRITE_FONT_STYLE_ITALIC;
                break;
            case SkFontStyle::kOblique_Slant:
                fSlant = DWRITE_FONT_STYLE_OBLIQUE;
                break;
            default:
                SkASSERT(false);
                break;
        }
    }
    DWRITE_FONT_WEIGHT fWeight;
    DWRITE_FONT_STRETCH fWidth;
    DWRITE_FONT_STYLE fSlant;
};

#endif
